package co.yixiang.yshop.module.order.service.storeaftersales;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.enums.OrderDefaultRuleEnum;
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.redis.util.RedissonUtil;
import co.yixiang.yshop.module.message.enums.WechatTempateEnum;
import co.yixiang.yshop.module.message.mq.message.WeixinNoticeMessage;
import co.yixiang.yshop.module.message.mq.producer.WeixinNoticeProducer;
import co.yixiang.yshop.module.order.controller.app.afterorder.param.AppProsuctParam;
import co.yixiang.yshop.module.order.controller.app.afterorder.param.AppReturnLogisticsParam;
import co.yixiang.yshop.module.order.controller.app.afterorder.param.AppStoreAfterSalesParam;
import co.yixiang.yshop.module.order.controller.app.afterorder.vo.*;
import co.yixiang.yshop.module.order.convert.storeaftersales.StoreAfterSalesConvert;
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersales.StoreAfterSalesDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersalesitem.StoreAfterSalesItemDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersalesstatus.StoreAfterSalesStatusDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeorderdetail.StoreOrderDetailDO;
import co.yixiang.yshop.module.order.dal.dataobject.storeorderstatus.StoreOrderStatusDO;
import co.yixiang.yshop.module.order.dal.mysql.storeaftersales.StoreAfterSalesMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeaftersalesitem.StoreAfterSalesItemMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeaftersalesstatus.StoreAfterSalesStatusMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeorder.StoreOrderMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo.StoreOrderCartInfoMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeorderdetail.StoreOrderDetailMapper;
import co.yixiang.yshop.module.order.dal.mysql.storeorderstatus.StoreOrderStatusMapper;
import co.yixiang.yshop.module.order.dal.redis.ofterorder.AfterOrderRedisDAO;
import co.yixiang.yshop.module.order.enums.*;
import co.yixiang.yshop.module.order.service.storeaftersalesstatus.StoreAfterSalesStatusService;
import co.yixiang.yshop.module.order.service.storeorderrule.StoreOrderRuleService;
import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusService;
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.enums.OrderInfoEnum.*;
import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.order.enums.AfterSalesStatusEnum.USER_CANCELLED;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.*;
import static co.yixiang.yshop.module.order.enums.OrderLogEnum.APPLY_AFTER_SALES;

/**
 * 售后记录 Service 实现类
 *
 * @author yshop
 */
@Service
@Slf4j
@Validated
public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMapper, StoreAfterSalesDO> implements AppStoreAfterSalesService {
    @Resource
    private StoreOrderMapper storeOrderMapper;
    @Resource
    private AfterOrderRedisDAO afterOrderRedisDAO;
    @Resource
    private StoreOrderCartInfoMapper storeOrderCartInfoMapper;
    @Resource
    private StoreAfterSalesItemMapper storeAfterSalesItemMapper;
    @Resource
    private StoreAfterSalesStatusMapper storeAfterSalesStatusMapper;
    @Resource
    private StoreAfterSalesStatusService storeAfterSalesStatusService;
    @Resource
    private StoreOrderStatusMapper storeOrderStatusMapper;
    @Resource
    private StoreOrderStatusService storeOrderStatusService;
    @Resource
    private StoreOrderRuleService storeOrderRuleService;

    @Resource
    private RedissonUtil redissonUtil;
    @Resource
    private StoreOrderDetailMapper orderDetailMapper;
    @Resource
    private WeixinNoticeProducer weixinNoticeProducer;

    /**
     * 创建售后订单
     *
     * @param userId               用户id
     * @param storeAfterSalesParam /
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Long applyForAfterSales(Long userId, AppStoreAfterSalesParam storeAfterSalesParam) {
        log.info("storeAfterSalesParam:{}", JSONObject.toJSONString(storeAfterSalesParam));
        // 查询订单信息
        StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(
                Wrappers.<StoreOrderDO>lambdaQuery()
                        .eq(StoreOrderDO::getOrderId, storeAfterSalesParam.getOrderId())
                        .eq(StoreOrderDO::getUid, userId)
        );

        //是否超过售后时间
        if (UNABLE_AFTER_SALES.getValue().equals(yxStoreOrder.getIsAfterSales())) {
            throw exception(ORDER_OUT_AFTER_SALE_TIME);
        }
        //自提切已经核销订单不可申请售后
        if (yxStoreOrder.getShippingType().equals(SHIPPING_TYPE_STORE_PICKUP.getValue()) && yxStoreOrder.getWriteOffStatus().equals(OrderWriteOffStatusEnum.WRITTEN_OFF.getValue())) {
            throw exception(ORDER_REFUND_NOT_STORE_PICKUP);
        }
        afterOrderRedisDAO.set(userId, storeAfterSalesParam.getOrderId(), yxStoreOrder.getStatus().toString());
        // checkOrder(yxStoreOrder);
        // 退款金额
        BigDecimal refundAmount = BigDecimal.ZERO;
        BigDecimal refundIntegral = BigDecimal.ZERO;
        //拿到所有的商品
        List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper.selectList(
                Wrappers.<StoreOrderCartInfoDO>lambdaQuery()
                        .eq(StoreOrderCartInfoDO::getOid, yxStoreOrder.getId())
        );
        // 查询出可以售后的订单明细
        List<StoreOrderDetailDO> orderDetailDOS = orderDetailMapper.selectList(Wrappers.<StoreOrderDetailDO>lambdaQuery()
                .eq(StoreOrderDetailDO::getOid, yxStoreOrder.getId())
                .eq(StoreOrderDetailDO::getState, OrderDetailStateEnum.NORMAL.getValue())
        );
        if (CollectionUtils.isEmpty(orderDetailDOS)) throw exception(ORDER_REFUND_NOT);
        // 订单明细 map
        Map<String, List<StoreOrderDetailDO>> orderDetailmap = orderDetailDOS
                .stream().collect(Collectors.groupingBy(StoreOrderDetailDO::getProductAttrUnique));
        // 售后物品明细
        List<StoreAfterSalesItemDO> insertAfterSalesItems = new ArrayList<>();
        // 发货标识
        boolean sendFlag = STATUS_DEFAULT.getValue().equals(yxStoreOrder.getStatus());
        // 参数提交的售后商品 map
        Map<String, AppProsuctParam> productParamMap = storeAfterSalesParam.getProductParamList()
                .stream().collect(Collectors.toMap(AppProsuctParam::getProductAttrUnique, Function.identity()));
        //需要售后的订单明细
        List<StoreOrderDetailDO> updateOrderDetails = new ArrayList<>();
        for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
            AppStoreCartQueryVo cartInfo = JSONObject.parseObject(yxStoreOrderCartInfo.getCartInfo(), AppStoreCartQueryVo.class);
            // 过滤出对应规格的商品
            AppProsuctParam productParam = productParamMap.get(cartInfo.getProductAttrUnique());
            List<StoreOrderDetailDO> skuOrderDetails = orderDetailmap.get(cartInfo.getProductAttrUnique());
            if (ObjectUtil.isNotNull(productParam) && productParam.getProductId() != null) {
                // 退款不可超过购买数量
                if (CollectionUtils.isEmpty(skuOrderDetails) || skuOrderDetails.size() < productParam.getNumber()) {
                    throw exception(ORDER_REFUND_NUMBER_LACK_ERROR);
                }
                // 计算退款金额
                refundAmount = refundAmount.add(NumberUtil.mul(yxStoreOrderCartInfo.getPayPrice(), productParam.getNumber()));
                //计算退款积分
                refundIntegral = refundIntegral.add(NumberUtil.mul(yxStoreOrderCartInfo.getUseIntegral(), productParam.getNumber()));
                // 未发货且全部退货退运费
                if (sendFlag && skuOrderDetails.size() == productParam.getNumber()) {
                    refundAmount = refundAmount.add(yxStoreOrderCartInfo.getPostagePrice());
                }
                yxStoreOrderCartInfo.setIsAfterSales(UNABLE_AFTER_SALES.getValue());
                storeOrderCartInfoMapper.updateById(yxStoreOrderCartInfo);
                // 售后明细
                StoreAfterSalesItemDO storeAfterSalesItem = new StoreAfterSalesItemDO();
                storeAfterSalesItem.setProductId(yxStoreOrderCartInfo.getProductId());
                cartInfo.setCartNum(productParam.getNumber());
                storeAfterSalesItem.setCartInfo(JSONObject.toJSONString(cartInfo));
                insertAfterSalesItems.add(storeAfterSalesItem);
                // 订单明细
                updateOrderDetails.addAll(skuOrderDetails.subList(0, productParam.getNumber()));
            }
        }
        //更新订单状态
        yxStoreOrder.setStatus(OrderInfoEnum.STATUS_APPLY_REFUND.getValue());
        yxStoreOrder.setRefundStatus(OrderInfoEnum.REFUND_STATUS_BEING_REFUNDED.getValue());
        yxStoreOrder.setRefundReasonWap(storeAfterSalesParam.getReasonForApplication());
        yxStoreOrder.setRefundReasonWapExplain(storeAfterSalesParam.getApplicationInstructions());
        yxStoreOrder.setRefundReasonTime(LocalDateTime.now());
        storeOrderMapper.updateById(yxStoreOrder);
        //生成售后订单
        StoreAfterSalesDO storeAfterSales = new StoreAfterSalesDO();
        storeAfterSales.setOrderCode(storeAfterSalesParam.getOrderId());
        storeAfterSales.setRefundAmount(refundAmount);
        storeAfterSales.setServiceType(storeAfterSalesParam.getServiceType());
        storeAfterSales.setReasons(storeAfterSalesParam.getReasonForApplication());
        storeAfterSales.setExplains(storeAfterSalesParam.getApplicationInstructions());
        storeAfterSales.setExplainImg(storeAfterSalesParam.getApplicationDescriptionPicture());
        storeAfterSales.setState(AfterSalesStatusEnum.PENDING_REVIEW.getValue());
        storeAfterSales.setReceivingStatus(storeAfterSalesParam.getReceivingStatus());
        storeAfterSales.setCreateTime(LocalDateTime.now());
        storeAfterSales.setUserId(userId);
        storeAfterSales.setRefundIntegral(refundIntegral);
        this.baseMapper.insert(storeAfterSales);

        insertAfterSalesItems.forEach(res -> res.setStoreAfterSalesId(storeAfterSales.getId()));
        // 售后明细批量保存
        storeAfterSalesItemMapper.insertBatch(insertAfterSalesItems);
        //订单明细修改为 售后中的状态
        updateOrderDetails.forEach(res -> {
            res.setAfterSalesId(storeAfterSales.getId());
            res.setState(OrderDetailStateEnum.IN_AFTER_SALES.getValue());
        });
        // 定单明细批量修改
        orderDetailMapper.updateBatch(updateOrderDetails, updateOrderDetails.size());
        // 记录订单操作
        storeOrderStatusService.create(yxStoreOrder.getUid(), yxStoreOrder.getId(),
                APPLY_AFTER_SALES.getValue(), APPLY_AFTER_SALES.getDesc());
        // 售后操作记录
        storeAfterSalesStatusService.create(storeAfterSales.getUserId(), storeAfterSales.getId(),
                AfterChangeTypeEnum.CREATE_AFTER_SALES.getValue(), AfterChangeTypeEnum.CREATE_AFTER_SALES.getDesc());
        // 提交售后之后自动通过售后（天)
        Integer autoAfterSalesPass = storeOrderRuleService.getOrderRuleCache().getAutoAfterSalesPass();
        //加入自动同意售后（通过售后请求）的延迟队列
        OrderDefaultRuleEnum ruleEnum = OrderDefaultRuleEnum.AFTER_SALES_ORDER_OUTTIME_UNCONFIRM;
        redissonUtil.delayedOffer(ruleEnum.getKey(), storeAfterSales.getId(), autoAfterSalesPass, ruleEnum.getUnit());

        //小程序
        weixinNoticeProducer.sendNoticeMessage( new WeixinNoticeMessage()
                .setUid(yxStoreOrder.getUid())
                .setOrderId(yxStoreOrder.getOrderId())
                .setTempkey(WechatTempateEnum.ORDER_AFTER_NOTICE.getValue())
                .setType(WechatTempateEnum.SUBSCRIBE.getValue()));
        //公众号
        weixinNoticeProducer.sendNoticeMessage( new WeixinNoticeMessage()
                .setUid(yxStoreOrder.getUid()).setOrderId(yxStoreOrder.getOrderId())
                .setTempkey(WechatTempateEnum.ORDER_AFTER_NOTICE.getValue())
                .setType(WechatTempateEnum.TEMPLATES.getValue()));

        return storeAfterSales.getId();
    }


    /**
     * 查询售后订单详情
     *
     * @param key 售后单号
     * @return 订单详情列表
     */
    @Override
    public AppStoreOrderAfterSalesDetailVo checkAfterSalesDetails(String key) {
        // 查询售后信息
        StoreAfterSalesDO afterSales = this.getById(Integer.parseInt(key));
        // 查询订单信息
        StoreOrderDO storeOrderDO = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery()
                .eq(StoreOrderDO::getOrderId, afterSales.getOrderCode()));

        // 查询售后信息子项
        List<StoreAfterSalesItemDO> afterSalesItemDOS =
                storeAfterSalesItemMapper.selectList(new LambdaUpdateWrapper<StoreAfterSalesItemDO>()
                        .eq(StoreAfterSalesItemDO::getStoreAfterSalesId, afterSales.getId()));

        List<AppStoreCartQueryVo> cartInfo =
                afterSalesItemDOS.stream().map(cart -> JSON.parseObject(cart.getCartInfo(), AppStoreCartQueryVo.class))
                        .collect(Collectors.toList());

        BigDecimal totalPrice = BigDecimal.ZERO;
        // 查询订单明细详情
        List<StoreOrderDetailDO> orderDetailDOS =
                orderDetailMapper.selectList(new LambdaQueryWrapper<StoreOrderDetailDO>()
                        .eq(StoreOrderDetailDO::getAfterSalesId, afterSales.getId()));
        Map<String, List<StoreOrderDetailDO>> orderDetailDOMap =
                orderDetailDOS.stream().collect(Collectors.groupingBy(StoreOrderDetailDO::getProductAttrUnique));
        for (AppStoreCartQueryVo cart : cartInfo) {
            totalPrice = totalPrice.add(cart.getTruePrice().multiply(BigDecimal.valueOf(cart.getCartNum())));
            cart.setCartNum(CollectionUtils.isNotEmpty(orderDetailDOMap.get(cart.getProductAttrUnique())) ?
                    orderDetailDOMap.get(cart.getProductAttrUnique()).size() : cart.getCartNum());
        }

        // 查询是否发货
        StoreOrderStatusDO orderStatusDO =
                storeOrderStatusMapper.selectOne(new LambdaQueryWrapper<StoreOrderStatusDO>()
                        .eq(StoreOrderStatusDO::getOid, storeOrderDO.getId())
                        .eq(StoreOrderStatusDO::getChangeType, OrderLogEnum.DELIVERY_GOODS.getValue()));
        //计算创建售后到自动确认时间
//        int offset = Integer.parseInt(String.valueOf(ShopConstants.ORDER_OUTTIME_UNCONFIRM));
        int offset = storeOrderRuleService.getOrderRuleCache().getAutoOrderTakeTime();
        log.info("time" + afterSales.getCreateTime());
        LocalDateTime time = afterSales.getCreateTime().plusDays(offset);
        long remainTime = afterSales.getState().equals(AfterStatusEnum.STATE_0.getValue()) ?
                time.toEpochSecond(ZoneOffset.ofHours(8)) * 1000 - System.currentTimeMillis() : 0;
        // 数据整合
        return AppStoreOrderAfterSalesDetailVo.builder()
                // 售后信息
                .id(afterSales.getId())
                .refundAmount(afterSales.getRefundAmount())
                .refundableIntegral(afterSales.getRefundIntegral())
                .reasons(afterSales.getReasons())
                .explains(afterSales.getExplains()).explainImg(afterSales.getExplainImg())
                .state(afterSales.getState()).salesState(afterSales.getSalesState())
                .realName(afterSales.getConsignee())
                .userPhone(afterSales.getPhoneNumber())
                .userAddress(afterSales.getAddress())
                .receivingStatus(afterSales.getReceivingStatus())
                .serviceType(afterSales.getServiceType())
                // 订单信息
                .orderId(storeOrderDO.getOrderId()).uid(storeOrderDO.getUid())
                .createTime(storeOrderDO.getCreateTime())
                .payPrice(storeOrderDO.getPayPrice())
                .totalPrice(totalPrice)
                .totalPostage(storeOrderDO.getTotalPostage()).deductionPrice(storeOrderDO.getDeductionPrice())
                .deliveryTime(orderStatusDO == null ? null : orderStatusDO.getChangeTime())
                .payTime(storeOrderDO.getPayTime())
                .couponPrice(storeOrderDO.getCouponPrice())
                .totalCouponPrice(storeOrderDO.getTotalCouponPrice())
                // 商品数据
                .cartInfo(cartInfo)
                // 物流数据
                .deliverySn(afterSales.getDeliverySn()).deliveryName(afterSales.getDeliveryName())
                .remainTime(String.valueOf(remainTime))
                .build();
    }

    /**
     * 查询订单详情
     *
     * @param vo
     * @return 订单详情列表
     */
    @Override
    public List<AppStoreOrderCartInfoVo> checkOrderDetails(AppAfterSalesDetailQueryVo vo) {
        LambdaQueryWrapper<StoreOrderCartInfoDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(i -> i.eq(StoreOrderCartInfoDO::getOrderId, vo.getKey())
                .or().eq(StoreOrderCartInfoDO::getUnique, vo.getKey()).or()
                .eq(StoreOrderCartInfoDO::getOid, vo.getKey()));
        List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper.selectList(wrapper);
        if (yxStoreOrderCartInfos == null || yxStoreOrderCartInfos.isEmpty()) {
            throw exception(STORE_ORDER_NOT_EXISTS);
        }
        // 查询订单信息
        StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery()
                .eq(StoreOrderDO::getOrderId, yxStoreOrderCartInfos.get(0).getOrderId()));
        // 查询可售后的订单详情
        List<StoreOrderDetailDO> orderDetailDOS =
                orderDetailMapper.selectList(Wrappers.<StoreOrderDetailDO>lambdaQuery()
                        .eq(StoreOrderDetailDO::getOid, yxStoreOrder.getId())
                        .eq(StoreOrderDetailDO::getState, OrderDetailStateEnum.NORMAL.getValue()));
        if (CollectionUtils.isEmpty(orderDetailDOS)) throw exception(ORDER_DETAIL_NOT_EXISTS);
        Map<String, List<StoreOrderDetailDO>> orderDetailDOSMap =
                orderDetailDOS.stream().collect(Collectors.groupingBy(StoreOrderDetailDO::getProductAttrUnique));

        List<AppStoreOrderCartInfoVo> yxStoreOrderCartInfoVos = new ArrayList<>();
        List<String> productAttrUniques = null;
        Map<String, Integer> productDetailMap = null;
        if (CollectionUtils.isNotEmpty(vo.getProductDetails())) {
            productAttrUniques = vo.getProductDetails().stream()
                    .map(AppAfterSalesProductDetailQueryVo::getGoods).collect(Collectors.toList());
            productDetailMap =
                    vo.getProductDetails().stream().collect(Collectors.toMap(e -> e.getGoods(), e -> e.getNumber()));
        }
        for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
            AppStoreCartQueryVo cartInfo =
                    JSONObject.parseObject(yxStoreOrderCartInfo.getCartInfo(), AppStoreCartQueryVo.class);
            if (CollectionUtils.isEmpty(orderDetailDOSMap.get(cartInfo.getProductAttrUnique()))) continue;
            // 记录总数
            Integer total = orderDetailDOSMap.get(cartInfo.getProductAttrUnique()).size();
            // 设置选中退款的总数
            if (ObjectUtil.isNotNull(productDetailMap) &&
                    ObjectUtil.isNotNull(productDetailMap.get(cartInfo.getProductAttrUnique()))) {
                total = productDetailMap.get(cartInfo.getProductAttrUnique());
            }
            if (CollectionUtils.isNotEmpty(productAttrUniques) &&
                    !productAttrUniques.contains(cartInfo.getProductAttrUnique())) {
                continue;
            }
            AppStoreOrderCartInfoVo yxStoreOrderCartInfoVo = new AppStoreOrderCartInfoVo();
            yxStoreOrderCartInfoVo.setId(yxStoreOrderCartInfo.getId());
            yxStoreOrderCartInfoVo.setOid(yxStoreOrderCartInfo.getOid());
            yxStoreOrderCartInfoVo.setOrderId(yxStoreOrderCartInfo.getOrderId());
            yxStoreOrderCartInfoVo.setCartId(yxStoreOrderCartInfo.getCartId());
            yxStoreOrderCartInfoVo.setProductId(yxStoreOrderCartInfo.getProductId());
            yxStoreOrderCartInfoVo.setCouponPrice(yxStoreOrderCartInfo.getCouponPrice());
            yxStoreOrderCartInfoVo.setPostagePrice(yxStoreOrderCartInfo.getPostagePrice());
            yxStoreOrderCartInfoVo.setUnique(yxStoreOrderCartInfo.getUnique());
            /*yxStoreOrderCartInfoVo.setIsAfterSales(yxStoreOrderCartInfo.getIsAfterSales() == null ?
                    0 : yxStoreOrderCartInfo.getIsAfterSales());*/
            // 设置可售后数量
            cartInfo.setCartNum(total);
            yxStoreOrderCartInfoVo.setCartInfo(cartInfo);
            yxStoreOrderCartInfoVo.setStatus(yxStoreOrder.getStatus());
            yxStoreOrderCartInfoVo.setRefundablePrice(yxStoreOrderCartInfo.getPayPrice());
            yxStoreOrderCartInfoVo.setRefundableIntegral(yxStoreOrderCartInfo.getUseIntegral());
            //  总优惠金额 = 商品价格 - 实际支付金额
            yxStoreOrderCartInfoVo.setTotalCouponPrice(NumberUtil.sub(cartInfo.getTruePrice(), yxStoreOrderCartInfo.getPayPrice()));
            yxStoreOrderCartInfoVos.add(yxStoreOrderCartInfoVo);
        }
        return yxStoreOrderCartInfoVos;

    }


    /**
     * 查询列表
     *
     * @param uid       用户id
     *                  //    * @param status    状态    //状态 0已提交等待平台审核 1平台已审核 等待用户发货/退款 2 用户已发货 3退款成功
     * @param page      页
     * @param orderCode 订单编码
     * @param limit     数量
     * @return List<AppStoreAfterSalesVo>
     */
    @Override
    public List<AppStoreAfterSalesVo> salesList(Long uid, Integer type, Integer page, String orderCode, Integer limit) {
        Page<StoreAfterSalesDO> storeAfterSalesPage = new Page<>(page, limit);
        List<Integer> afterSalesStatusList = getAfterSalesStatus(type);
        LambdaQueryWrapper<StoreAfterSalesDO> wrappers = new LambdaQueryWrapper<>();
        wrappers.eq(uid != null, StoreAfterSalesDO::getUserId, uid)
                .in(!type.equals(AfterSalesStatusEnum.PENDING_REVIEW.getValue()), StoreAfterSalesDO::getState, afterSalesStatusList)
                .eq(StringUtils.isNotBlank(orderCode), StoreAfterSalesDO::getOrderCode, orderCode);
        baseMapper.selectPage(storeAfterSalesPage, wrappers.
                orderByDesc(StoreAfterSalesDO::getCreateTime));

        List<AppStoreAfterSalesVo> storeAfterSalesVos =
                StoreAfterSalesConvert.INSTANCE.convertList1(storeAfterSalesPage.getRecords());
        return storeAfterSalesVos.stream().map(this::handleSales).collect(Collectors.toList());
    }

    private static List<Integer> getAfterSalesStatus(Integer status) {
        List<Integer> afterSalesStatusList = new ArrayList<>();
        if (status == 1) {
            afterSalesStatusList.add(AfterSalesStatusEnum.PENDING_REVIEW.getValue());
            afterSalesStatusList.add(AfterSalesStatusEnum.AUDITED.getValue());
            afterSalesStatusList.add(AfterSalesStatusEnum.USER_SHIPPED.getValue());
            afterSalesStatusList.add(AfterSalesStatusEnum.MERCHANT_REJECTION.getValue());
        } else if (status == 2) {
            afterSalesStatusList.add(AfterSalesStatusEnum.REFUND_SUCCESS.getValue());
            afterSalesStatusList.add(AfterSalesStatusEnum.USER_CANCELLED.getValue());
        } else {
            afterSalesStatusList.addAll(Arrays.stream(AfterSalesStatusEnum.values())
                    .map(AfterSalesStatusEnum::getValue).collect(Collectors.toList()));
        }
        return afterSalesStatusList;
    }


    /**
     * 查询详情
     *
     * @param key 订单号
     * @param id  售后单id
     * @param uid 用户id
     */
    @Override
    public AppStoreAfterSalesVo getStoreInfoByOrderCodeAndAfterIdAndUid(String key, Long id, Long uid) {
        if (StrUtil.isEmpty(key)) {
            throw exception(PARAM_ERROR);
        }
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(id != null, StoreAfterSalesDO::getId, id)
                .eq(StoreAfterSalesDO::getUserId, uid)
                .eq(StoreAfterSalesDO::getOrderCode, key));

        AppStoreAfterSalesVo salesVo = StoreAfterSalesConvert.INSTANCE.convert1(storeAfterSales);
        return this.handleSales(salesVo);
    }

    /**
     * 查询详情
     *
     * @param key 订单号
     * @param uid 用户id
     */
    @Override
    public List<AppStoreAfterSalesVo> getStoreInfoByOrderCodeAndUid(String key, Long uid) {
        if (StrUtil.isEmpty(key)) {
            throw exception(PARAM_ERROR);
        }
        List<StoreAfterSalesDO> storeAfterSales = baseMapper.selectList(Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(StoreAfterSalesDO::getUserId, uid)
                .eq(StoreAfterSalesDO::getOrderCode, key));
        if (ObjectUtil.isNull(storeAfterSales)) {
            throw exception(STORE_AFTER_SALES_NOT_EXISTS);
        }
        List<AppStoreAfterSalesVo> list = StoreAfterSalesConvert.INSTANCE.convertList1(storeAfterSales);
        list.forEach(this::handleSales);

        return list;
    }

    /**
     * 撤销申请
     *
     * @param key 订单号
     * @param uid 用户id
     * @param id  Long
     * @return Boolean
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean revoke(String key, Long uid, Long id) {
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(StoreAfterSalesDO::getUserId, uid)
                .eq(StoreAfterSalesDO::getId, id)
                .eq(StoreAfterSalesDO::getOrderCode, key));
        if (StrUtil.isEmpty(key)) {
            throw exception(PARAM_ERROR);
        }
        if (storeAfterSales == null) {
            throw exception(STORE_AFTER_SALES_NOT_EXISTS);
        }
        if (storeAfterSales.getState().equals(AfterSalesStatusEnum.USER_SHIPPED.getValue()) || storeAfterSales.getState().equals(AfterSalesStatusEnum.REFUND_SUCCESS.getValue())) {
            throw exception(ORDER_NOT_REVOKE);
        }
        // storeAfterSales.setSalesState(1);
        storeAfterSales.setState(USER_CANCELLED.getValue());

        StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery().eq(StoreOrderDO::getOrderId, key));
        String o = afterOrderRedisDAO.get(key, uid);
        yxStoreOrder.setStatus(o == null ? 0 : Integer.parseInt(o));
        yxStoreOrder.setRefundStatus(STATUS_DEFAULT.getValue());
        storeOrderMapper.updateById(yxStoreOrder);

        List<StoreOrderCartInfoDO> yxStoreOrderCartInfos =
                storeOrderCartInfoMapper.selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery()
                        .eq(StoreOrderCartInfoDO::getOid, yxStoreOrder.getId()));
        for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
            yxStoreOrderCartInfo.setIsAfterSales(ShopCommonEnum.YES.getValue());
            storeOrderCartInfoMapper.updateById(yxStoreOrderCartInfo);
        }

        // 修改订单明细状态
        orderDetailMapper.update(null, new LambdaUpdateWrapper<StoreOrderDetailDO>()
                .eq(StoreOrderDetailDO::getAfterSalesId, id)
                .set(StoreOrderDetailDO::getState, OrderDetailStateEnum.NORMAL.getValue())
        );

        //操作记录
        storeAfterSalesStatusService.create(storeAfterSales.getUserId(), storeAfterSales.getId(),
                AfterChangeTypeEnum.USER_REVOCATION.getValue(), AfterChangeTypeEnum.USER_REVOCATION.getDesc());

        afterOrderRedisDAO.delete(key, uid);
        return baseMapper.updateById(storeAfterSales) > 0;
    }

    /**
     * 添加退货的快递信息
     *
     * @param param 退货物流参数
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean addLogisticsInformation(AppReturnLogisticsParam param) {
        StoreAfterSalesDO storeAfterSales = getById(param.getId());
        // .eq(StoreAfterSalesDO::getOrderCode, param.getOrderCode()));
        if (!storeAfterSales.getState().equals(AfterSalesStatusEnum.AUDITED.getValue())) {
            throw exception(ORDER_STATUS_NOT_EXPRESS_);
        }
        storeAfterSales.setShipperCode(param.getCode());
        storeAfterSales.setDeliverySn(param.getPostalCode());
        storeAfterSales.setDeliveryName(param.getName());
        storeAfterSales.setReturnPolicy(param.getReturnPolicy());
        storeAfterSales.setReturnVoucher(param.getReturnVoucher());
        storeAfterSales.setState(AfterSalesStatusEnum.USER_SHIPPED.getValue());

        //操作记录
        storeAfterSalesStatusService.create(storeAfterSales.getUserId(), storeAfterSales.getId(),
                AfterChangeTypeEnum.USER_SHIPMENT.getValue(), AfterChangeTypeEnum.USER_SHIPMENT.getDesc());
        boolean b = baseMapper.updateById(storeAfterSales) > 0;
        if (b) {
            //用户寄回商品后多少天自动通过售后
            Integer afterSalesOrderAutoSucceed = storeOrderRuleService.getOrderRuleCache().getAfterSalesOrderAutoSucceed();
            OrderDefaultRuleEnum ruleEnum = OrderDefaultRuleEnum.AFTER_SALES_ORDER_USER_RETURN_GOODS_CONFIRM;
            redissonUtil.delayedOffer(
                    ruleEnum.getKey(), storeAfterSales.getId(), afterSalesOrderAutoSucceed, ruleEnum.getUnit()
            );
        }
        return b;
    }

    /**
     * 删除售后订单
     *
     * @param orderCode /
     * @param id        售后订单id
     * @return /
     */
    @Override
    public Boolean deleteAfterSalesOrder(String orderCode, Long id) {
        if (StrUtil.isEmpty(orderCode) || ObjectUtil.isEmpty(id)) {
            throw exception(PARAM_ERROR);
        }
        StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery()
                .eq(StoreAfterSalesDO::getId, id)
                .eq(StoreAfterSalesDO::getOrderCode, orderCode));
        return baseMapper.deleteById(storeAfterSales.getId()) > 0;
    }

    /**
     * 处理售后订单返回的状态
     *
     * @param storeAfterSalesVo /
     * @return StoreAfterSalesVo /
     */
    private AppStoreAfterSalesVo handleSales(AppStoreAfterSalesVo storeAfterSalesVo) {
        List<StoreAfterSalesItemDO> storeAfterSalesItems = storeAfterSalesItemMapper.selectList(Wrappers.<StoreAfterSalesItemDO>lambdaQuery().eq(StoreAfterSalesItemDO::getStoreAfterSalesId, storeAfterSalesVo.getId()));
        List<AppStoreCartQueryVo> cartInfo = storeAfterSalesItems.stream().map(cart -> JSON.parseObject(cart.getCartInfo(), AppStoreCartQueryVo.class)).collect(Collectors.toList());
        // 查询订单明细详情
        List<StoreOrderDetailDO> orderDetailDOS =
                orderDetailMapper.selectList(new LambdaQueryWrapper<StoreOrderDetailDO>()
                        .eq(StoreOrderDetailDO::getAfterSalesId, storeAfterSalesVo.getId()));
        Map<String, List<StoreOrderDetailDO>> orderDetailDOMap =
                orderDetailDOS.stream().collect(Collectors.groupingBy(StoreOrderDetailDO::getProductAttrUnique));
        cartInfo.forEach(res -> {
            res.setCartNum(CollectionUtils.isNotEmpty(orderDetailDOMap.get(res.getProductAttrUnique())) ?
                    orderDetailDOMap.get(res.getProductAttrUnique()).size() : res.getCartNum());
        });
        storeAfterSalesVo.setCartInfo(cartInfo);
        List<StoreAfterSalesStatusDO> storeAfterSalesStatuses =
                storeAfterSalesStatusMapper.selectList(Wrappers.<StoreAfterSalesStatusDO>lambdaQuery()
                        .eq(StoreAfterSalesStatusDO::getStoreAfterSalesId, storeAfterSalesVo.getId()));

        StoreOrderDO storeOrderDO =
                storeOrderMapper.selectOne(new LambdaQueryWrapper<StoreOrderDO>()
                        .eq(StoreOrderDO::getOrderId, storeAfterSalesVo.getOrderCode()));
        if (storeOrderDO != null) {
            storeAfterSalesVo.setOrderId(storeOrderDO.getId());
            storeAfterSalesVo.setCompleteTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 3).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
            storeAfterSalesVo.setDeliveryTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 2).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
            storeAfterSalesVo.setAuditFailedTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 4).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
            storeAfterSalesVo.setReviewTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 1).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
            storeAfterSalesVo.setRevocationTime(storeAfterSalesStatuses.stream().filter(item -> item.getChangeType() == 5).findFirst().orElse(new StoreAfterSalesStatusDO()).getChangeTime());
        }
        return storeAfterSalesVo;
    }

    /**
     * 检查订单是否符合售后订单
     *
     * @param yxStoreOrder 订单
     */
    private void checkOrder(StoreOrderDO yxStoreOrder) {
        if (yxStoreOrder == null) {
            throw exception(STORE_ORDER_NOT_EXISTS);
        }

        if (!yxStoreOrder.getPaid().equals(OrderInfoEnum.PAY_STATUS_HAVE_PAID.getValue()) || !yxStoreOrder.getRefundStatus().equals(OrderInfoEnum.REFUND_STATUS_NORMAL.getValue()) || yxStoreOrder.getStatus() < STATUS_DEFAULT.getValue() || yxStoreOrder.getIsAfterSales().equals(UNABLE_AFTER_SALES.getValue())) {
            throw exception(ORDER_REFUND_NOT);
        }
    }


}
